package com.bakend.modules.chat;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class ChatServer {
    private static final Logger logger = LogManager.getLogger(ChatServer.class);

    private final EventLoopGroup bossGroup = new NioEventLoopGroup();
    private final EventLoopGroup workGroup = new NioEventLoopGroup();
    private final ServerBootstrap server = new ServerBootstrap();
    private boolean isListen;


    public ChatServer(String serverName) {
        isListen = false;
    }


    public void start(ChannelInitializer<SocketChannel> channel) {
        if (isListen) {
            return;
        }
        //option()是提供给NioServerSocketChannel用来接收进来的连接,也就是boss线程。
        //childOption()是提供给由父管道ServerChannel接收到的连接，也就是worker线程
        server.group(bossGroup, workGroup);
        server.childHandler(channel);
        server.channel(NioServerSocketChannel.class);
        server.option(ChannelOption.SO_SNDBUF, 2048 * 1024);//发送缓冲器
        server.option(ChannelOption.SO_RCVBUF, 512 * 1024);
        server.childOption(ChannelOption.TCP_NODELAY, true)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.SO_REUSEADDR, true);     //重用地址
        server.option(ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator.DEFAULT);
        server.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
        server.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
        server.childOption(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK, 2048 * 1024);
        server.childOption(ChannelOption.WRITE_BUFFER_LOW_WATER_MARK, 512 * 1024);
//        server.childOption(ChannelOption.SO_BACKLOG, 512 * 1024);//全连接队列大小
        ChannelFuture f = server.bind(9998);
        isListen = true;
        f.addListener((ChannelFutureListener) future -> {
            if (future.isSuccess()) {
                logger.info(  "聊天服务监听 9998 成功！");
            } else {
                logger.error("聊天服务监听监听 9998失败！退出");
                System.exit(1);
            }
        });
        try {
            f.channel().closeFuture().sync();
        } catch (InterruptedException ex) {
            logger.error("聊天服务监听监听 9998失败！退出", ex);
            System.exit(1);
        }
    }

    public void stop() {
        if (isListen) {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
        isListen = false;
    }
}
